Startup
library(tidyverse)
library(cowplot)
library(ggpmisc)
source("data_import_functions.R")
source("calculation_functions.R")
source("figure_format_functions.R")
all_hla_expanded <- readRDS("all_hla_expanded.RDS")
isb_path <- "/labs/khatrilab/solomonb/covid/isb"
isb_samples <- read_tsv("/labs/khatrilab/solomonb/covid/isb/logs/210217_232725/parallel.log") %>%
separate(Command, into = c(NA, "sample"), sep = " ") %>%
pull(sample) %>% unique()
Get arcasHLA alignment stats
hla_mapping_stats_import_v2 <- function(samples, log_dir){
tibble(sample = samples) %>%
mutate(data = map(sample, function(x){
log_path <- sprintf("%s/%s.genotype.log",log_dir,x)
df <- tibble(lines = read_lines(log_path))
if (any(grepl("error", df$lines, ignore.case = T))){
NA
} else {
total_reads <- df %>%
mutate(lines = gsub("\t", "", lines)) %>%
filter(grepl("^\\[alignment\\] Processed", lines)) %>%
mutate(lines = gsub("\\,.*", "", lines)) %>%
mutate(lines = str_extract(lines, "[0-9]+")) %>%
pull(lines) %>%
as.numeric()
df %>%
mutate(lines = gsub("\t", "", lines)) %>%
filter(grepl("^HLA", lines)) %>%
separate(lines, into = c("locus", "abundance", "reads", "classes"), sep = " +") %>%
mutate(total_reads = total_reads) %>%
mutate(total_hla_reads = sum(as.numeric(reads)))
}
})) %>%
unnest(data) %>%
select(!(contains("data"))) %>%
separate(locus, into = c(NA, "locus"), sep = "-") %>%
mutate_at(c("reads", "classes"), as.numeric)
}
arcas_log_dir <- sprintf("%s/arcasHLA", isb_path)
alignment_stats_df <- hla_mapping_stats_import_v2(isb_samples, arcas_log_dir) %>%
filter(grepl("^[ABC]|^D[PQR][AB]1", locus) & grepl("-(AC|BL)$", sample))%>%
mutate(reads = total_reads)
alignment_stats_df
Import cell counts
cell_counts_df <- readRDS("isb_sequenced_cell_count.RDS")
cell_counts_df
Coverage based plots
gg_coverage(accuracy_df, x_var = "reads", y_var = "accuracy")
`geom_smooth()` using formula 'y ~ x'

gg_coverage(accuracy_df, x_var = "coverage", y_var = "success")
`geom_smooth()` using formula 'y ~ x'

gg_coverage(accuracy_df, x_var = "coverage", y_var = "n_alleles", facet_genotyper = T)

Cell number based plots
gg_coverage(accuracy_df, x_var = "n_cells", y_var = "accuracy")
`geom_smooth()` using formula 'y ~ x'

gg_coverage(accuracy_df, x_var = "n_cells", y_var = "success")
`geom_smooth()` using formula 'y ~ x'

gg_coverage(accuracy_df, x_var = "n_cells", y_var = "n_alleles", facet_genotyper = T)

Subsample READS
Import read subsample data
# Import predicted genotypes
subsample_reads_path <- "/labs/khatrilab/solomonb/covid/isb/subsample"
subsample_reads_samples <- tibble(sample = list.files(sprintf("%s/arcasHLA", subsample_reads_path))) %>%
filter(grepl("^INCOV", sample)) %>%
separate(sample, into = c("sample"), sep = "\\.", extra = "drop") %>%
distinct() %>%
pull(sample)
subsample_reads_df <- format_hla_table(combine_HLA_import(path = subsample_reads_path, samples = subsample_reads_samples))
subsample_reads_df <- subsample_reads_df %>%
filter(grepl("^[ABC]|D.[AB]1", locus) & grepl("-(AC|BL)_", sample))
subsample_reads_df
# Expand invitro genotypes across read subsample names
invitro_df <- invitro_import()
Rows: 1557 Columns: 9
── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: "\t"
chr (8): Sample ID, Locus, Allele 1, Allele 2, Comments, Diploid Ambiguities, Allele 1 Ambiguities, Allele 2 Ambiguities
dbl (1): index
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
invitro_reads_df <- subsample_reads_df %>%
select(sample) %>%
distinct() %>%
separate(sample, into = c("sample", "subsample"), sep = "_") %>%
left_join(invitro_df, by = "sample") %>%
unite(sample, sample, subsample, sep = "_") %>%
format_hla_table() %>%
drop_na()
invitro_reads_df
# Import read statistics
subsample_reads_arcas_log_dir <- sprintf("%s/arcasHLA", subsample_reads_path)
subsample_reads_alignment_stats_df <- hla_mapping_stats_import(subsample_reads_samples, subsample_reads_arcas_log_dir)
Calculate accuracy
# Calculate accuracy
subsample_reads_accuracy_df <- compare_hla(
hla_df = bind_rows(
subsample_reads_df,
invitro_reads_df
),
reference = "invitro",
method = "accuracy"
)
# saveRDS(subsample_reads_accuracy_df, "isb_subsample_reads_accuracy.RDS")
# Calculate success
subsample_reads_success_df <- compare_hla(
hla_df = bind_rows(
subsample_reads_df,
invitro_reads_df
),
reference = "invitro",
method = "success"
)
# saveRDS(subsample_reads_success_df, "isb_subsample_reads_success.RDS")
subsample_reads_accuracy_df <- readRDS("isb_subsample_reads_accuracy.RDS")
subsample_reads_success_df <- readRDS("isb_subsample_reads_success.RDS")
# Combine various data
subsample_reads_combined_df <- subsample_reads_accuracy_df %>%
left_join(
subsample_reads_success_df %>% select(sample:field, genotyper, success = accuracy),
by = c("sample", "locus", "field", "genotyper")
)%>%
left_join(subsample_reads_alignment_stats_df, by = c("sample", "locus")) %>%
left_join(genome_region_reference, by = "locus") %>%
bind_rows(accuracy_df %>% select(-n_cells)) %>% # No cell numbers for read subsamples
mutate_at(vars(c(reads, bp)), as.numeric) %>%
mutate(coverage = (reads * 91)/bp) %>% # Calculate coverage
mutate(n_alleles = map_dbl(allele, function(x) sum(!is.na(x)))) %>% # Calculate n_alleles
filter(grepl("^[ABC]|D.[AB]1", locus) & grepl("-(AC|BL)", sample) & genotyper != "hlaminer")
Reads plots
gg_coverage(subsample_reads_combined_df, x_var = "reads", y_var = "accuracy")
`geom_smooth()` using formula 'y ~ x'

plt_read_accuracy_all <- gg_coverage(subsample_reads_combined_df, x_var = "reads", y_var = "accuracy")
plt_read_accuracy_abc <- gg_coverage(subsample_reads_combined_df %>% filter(grepl("^[ABC]", locus)), x_var = "reads", y_var = "accuracy")
gg_coverage(subsample_reads_combined_df, x_var = "reads", y_var = "success")
`geom_smooth()` using formula 'y ~ x'

plt_read_success_all <- gg_coverage(subsample_reads_combined_df, x_var = "reads", y_var = "success")
plt_read_success_abc <- gg_coverage(subsample_reads_combined_df %>% filter(grepl("^[ABC]", locus)), x_var = "reads", y_var = "success")
gg_coverage(subsample_reads_combined_df, x_var = "reads", y_var = "n_alleles", facet_genotyper = T)

plt_read_allele_all <- gg_coverage(subsample_reads_combined_df, x_var = "reads", y_var = "n_alleles", facet_genotyper = T)
plt_read_allele_abc <- gg_coverage(subsample_reads_combined_df %>% filter(grepl("^[ABC]", locus)), x_var = "reads", y_var = "n_alleles", facet_genotyper = T)
- Default arcasHLA cut off 75 reads (log10 = 1.8)
subsample_reads_combined_df %>%
filter(field == "field_2") %>%
mutate(n_alleles = factor(n_alleles, levels = 0:2)) %>%
ggplot(aes(y = n_alleles, x = log10(coverage)))+
# geom_violin(scale = "count", alpha = 0.5, )+
geom_jitter(size = 0.2, width = 0, height =0.2, alpha = 0.2)+
# geom_boxplot(width=0.1)+
# ggbeeswarm::geom_beeswarm(size = 0.1, alpha = 0.1)+
# coord_flip()+
facet_grid(genotyper ~ locus, scales = "free")+
theme_bw()
Subsample CELLS
# Import predicted genotypes
subsample_cells_path <- "/labs/khatrilab/solomonb/covid/isb/subsample_cells"
subsample_cells_samples <- tibble(sample = list.files(sprintf("%s/arcasHLA", subsample_cells_path))) %>%
filter(grepl("^INCOV", sample)) %>%
separate(sample, into = c("sample"), sep = "\\.", extra = "drop") %>%
distinct() %>%
pull(sample)
subsample_cells_df <- format_hla_table(combine_HLA_import(path = subsample_cells_path, samples = subsample_cells_samples))
subsample_cells_df <- subsample_cells_df %>%
filter(grepl("^[ABC]|D.[AB]1", locus) & grepl("-(AC|BL)_", sample))
subsample_cells_df
# Expand invitro genotypes across read subsample names
invitro_df <- invitro_import()
invitro_cells_df <- subsample_cells_df %>%
select(sample) %>%
distinct() %>%
separate(sample, into = c("sample", "subsample"), sep = "_") %>%
left_join(invitro_df, by = "sample") %>%
unite(sample, sample, subsample, sep = "_") %>%
format_hla_table() %>%
drop_na()
invitro_cells_df
# Import read statistics
subsample_cells_arcas_log_dir <- sprintf("%s/arcasHLA", subsample_cells_path)
subsample_cells_alignment_stats_df <- hla_mapping_stats_import(subsample_cells_samples, subsample_cells_arcas_log_dir)
# Import cell counts for each subsample
subsample_cell_counts_df <- tibble(line = system("wc -l /labs/khatrilab/solomonb/covid/isb/subsample_cells/barcodes/INCOV*", intern = T)) %>%
separate(line, into = c("n_cells", "file"), sep = " /") %>%
drop_na() %>%
mutate(sample = gsub("\\..*","",basename(file))) %>%
select(-file) %>%
separate(sample, into = c("sample", "subset"), sep = "_")
subsample_cell_counts_df
Calculate accuracy
# Calculate accuracy
subsample_cells_accuracy_df <- compare_hla(
hla_df = bind_rows(
subsample_cells_df,
invitro_cells_df
),
reference = "invitro",
method = "accuracy"
)
# saveRDS(subsample_cells_accuracy_df, "isb_subsample_cells_accuracy.RDS")
# Calculate success
subsample_cells_success_df <- compare_hla(
hla_df = bind_rows(
subsample_cells_df,
invitro_cells_df
),
reference = "invitro",
method = "success"
)
# saveRDS(subsample_cells_success_df, "isb_subsample_cells_success.RDS")
# Combine various data
subsample_cells_combined_df <- subsample_cells_accuracy_df %>%
left_join(
subsample_cells_success_df %>% select(sample:field, genotyper, success = accuracy),
by = c("sample", "locus", "field", "genotyper")
)%>%
left_join(subsample_cells_alignment_stats_df, by = c("sample", "locus")) %>%
left_join(genome_region_reference, by = "locus") %>%
left_join(cell_counts_df, by = "sample") %>%
bind_rows(accuracy_df) %>%
mutate_at(vars(c(reads, bp)), as.numeric) %>%
mutate(coverage = (reads * 91)/bp) %>%
mutate(n_alleles = map_dbl(allele, function(x) sum(!is.na(x)))) %>%
filter(grepl("^[ABC]|D.[AB]1", locus) & grepl("-(AC|BL)", sample) & genotyper != "hlaminer")
Coverage plots
gg_coverage(subsample_cells_combined_df, x_var = "coverage", y_var = "accuracy")
gg_coverage(subsample_cells_combined_df, x_var = "coverage", y_var = "success")
gg_coverage(subsample_cells_combined_df, x_var = "coverage", y_var = "n_alleles", facet_genotyper = T)
Cell number plots
gg_coverage(subsample_cells_combined_df, x_var = "n_cells", y_var = "accuracy")

plt_cell_accuracy_all <- gg_coverage(subsample_cells_combined_df, x_var = "n_cells", y_var = "accuracy")
plt_cell_accuracy_abc <- gg_coverage(subsample_cells_combined_df %>% filter(grepl("^[ABC]", locus)), x_var = "n_cells", y_var = "accuracy")
gg_coverage(subsample_cells_combined_df, x_var = "n_cells", y_var = "success")

plt_cell_success_all <- gg_coverage(subsample_cells_combined_df, x_var = "n_cells", y_var = "success")
plt_cell_success_abc <- gg_coverage(subsample_cells_combined_df %>% filter(grepl("^[ABC]", locus)), x_var = "n_cells", y_var = "success")
gg_coverage(subsample_cells_combined_df, x_var = "n_cells", y_var = "n_alleles", facet_genotyper = T)

plt_cell_allele_all <- gg_coverage(subsample_cells_combined_df, x_var = "n_cells", y_var = "n_alleles", facet_genotyper = T)
plt_cell_allele_abc <- gg_coverage(subsample_cells_combined_df %>% filter(grepl("^[ABC]", locus)), x_var = "n_cells", y_var = "n_alleles", facet_genotyper = T)
Combined plots
no_leg <- list(theme(legend.position = "none"))
legend <- cowplot::get_legend(plt_read_accuracy_abc)
plot_grid(
plot_grid(
plt_read_accuracy_abc + no_leg,
plt_read_success_abc + no_leg,
plt_read_allele_abc,
ncol = 1,
align = "v",
axis = "lr",
rel_heights = c(1,1,1.2),
labels = LETTERS[1:3]
),
plot_grid(
plt_cell_accuracy_abc + no_leg,
plt_cell_success_abc + no_leg,
plt_cell_allele_abc,
ncol = 1,
align = "v",
axis = "lr",
rel_heights = c(1,1,1.2),
labels = LETTERS[4:6]
),
plot_grid(
legend,
legend,
NA,
ncol = 1
),
nrow = 1,
rel_widths = c(1,1,0.25)
)

no_leg <- list(theme(legend.position = "none"))
legend <- cowplot::get_legend(plt_read_accuracy_all)
plot_grid(
plot_grid(
plt_read_accuracy_all + no_leg,
plt_read_success_all + no_leg,
plt_read_allele_all,
ncol = 1,
align = "v",
axis = "lr",
rel_heights = c(1,1,1.2),
labels = LETTERS[1:3]
),
plot_grid(
plt_cell_accuracy_all + no_leg,
plt_cell_success_all + no_leg,
plt_cell_allele_all,
ncol = 1,
align = "v",
axis = "lr",
rel_heights = c(1,1,1.2),
labels = LETTERS[4:6]
),
plot_grid(
legend,
legend,
NA,
ncol = 1
),
nrow = 1,
rel_widths = c(1,1,0.25)
)

Slope stats
get_lm_stats <- function(df, x_var = "coverage", y_var = "accuracy", field_var = "field_2", x_log = T){
# Input checks
arg_col <- makeAssertCollection()
assertChoice(y_var, c("accuracy", "success", "n_alleles"), add = arg_col)
assertChoice(x_var, c("reads", "coverage", "n_cells"), add = arg_col)
assertChoice(field_var, c("field_1", "field_2", "field_3"), add = arg_col)
assertLogical(x_log, add = arg_col)
if (arg_col$isEmpty()==F) {map(arg_col$getMessages(),print);reportAssertions(arg_col)}
# browser()
df <- df %>%
filter(field == field_var) %>%
remove_invalid_combinations()
if (x_log ==T){df <- df %>% mutate_at(x_var, log10)}
df %>%
filter_at(x_var, function(x) !is.na(x) & !is.infinite(x)) %>%
group_by(locus, field, genotyper) %>%
nest() %>%
mutate(data = map(data, function(x){
summary(lm(!!sym(y_var) ~ !!sym(x_var), data = x)) %>% broom::tidy() %>% filter(term == x_var)
})) %>% unnest_wider(data) %>%
mutate(est_min = round(estimate - 2*std.error, 2),
est_max = round(estimate + 2*std.error, 2))
}
model_stats <- get_lm_stats(subsample_cells_combined_df, x_var = "reads", y_var = "accuracy", x_log = T)
model_stats
model_stats <- bind_rows(
get_lm_stats(subsample_reads_combined_df, x_var = "reads", y_var = "accuracy", x_log = T) %>% mutate(x_var = "reads", y_var = "accuracy"),
get_lm_stats(subsample_reads_combined_df, x_var = "reads", y_var = "success", x_log = T) %>% mutate(x_var = "reads", y_var = "success"),
get_lm_stats(subsample_cells_combined_df, x_var = "n_cells", y_var = "accuracy", x_log = T) %>% mutate(x_var = "cells", y_var = "accuracy"),
get_lm_stats(subsample_cells_combined_df, x_var = "n_cells", y_var = "success", x_log = T) %>% mutate(x_var = "cells", y_var = "success")
) %>%
# filter(grepl("^[ABC]", locus)) %>%
ungroup() %>%
filter(field == "field_2")
Table
| Reads | Cells |
| A | B | C | DPA1 | DPB1 | DQA1 | DQB1 | DRB1 | A | B | C | DPA1 | DPB1 | DQA1 | DQB1 | DRB1 |
Accuracy | arcasHLA | (0.09) - (0.14) | (0.09) - (0.14) | (0.11) - (0.15) | (0.26) - (0.29) | (0.23) - (0.28) | (0.26) - (0.3) | (0.23) - (0.27) | (0.19) - (0.24) | (-0.27) - (0.03) | (-0.31) - (0.01) | (-0.22) - (0.09) | (-0.15) - (0) | (-0.22) - (0.02) | (-0.31) - (-0.09) | (-0.22) - (0.05) | (-0.31) - (-0.08) |
OptiType | (-0.05) - (0) | (-0.03) - (0.02) | (-0.01) - (0.03) | --- | --- | --- | --- | --- | (-0.63) - (-0.32) | (-0.57) - (-0.28) | (-0.54) - (-0.24) | --- | --- | --- | --- | --- |
PHLAT | (0.05) - (0.1) | (0.07) - (0.12) | (0.08) - (0.12) | --- | --- | (0.18) - (0.22) | (0.18) - (0.22) | (0.13) - (0.18) | (-0.27) - (-0.01) | (-0.4) - (-0.13) | (-0.19) - (0.06) | --- | --- | (-0.25) - (-0.02) | (-0.21) - (-0.01) | (-0.28) - (-0.04) |
Success | arcasHLA | (-0.07) - (0.01) | (-0.01) - (0.07) | (-0.01) - (0.07) | (0.04) - (0.11) | (-0.01) - (0.09) | (-0.04) - (0.06) | (-0.04) - (0.08) | (-0.04) - (0.03) | (-0.39) - (0.03) | (-0.42) - (0.04) | (-0.35) - (0.08) | (-0.21) - (0.03) | (-0.35) - (0.05) | (-0.35) - (-0.03) | (-0.3) - (0.11) | (-0.39) - (-0.04) |
OptiType | (0.01) - (0.06) | (0.03) - (0.08) | (0.05) - (0.09) | --- | --- | --- | --- | --- | (-0.35) - (0.06) | (-0.29) - (0.07) | (-0.15) - (0.17) | --- | --- | --- | --- | --- |
PHLAT | (0.05) - (0.1) | (0.08) - (0.13) | (0.08) - (0.12) | --- | --- | (0.12) - (0.18) | (0.11) - (0.17) | (0.12) - (0.17) | (-0.34) - (0.05) | (-0.64) - (-0.25) | (-0.3) - (0.05) | --- | --- | (-0.32) - (0.02) | (-0.27) - (0.04) | (-0.36) - (0.01) |
df <- df %>%
mutate(field = reformat_hla_field(field)) %>%
mutate_at(vars(contains("genotyper")), reformat_hla_genotyper) %>%
mutate(cell_value = ifelse(!is.na(se),
sprintf("%s %s %s", round(mean_accuracy,2),"\u00B1",round(se,2)),
sprintf("%s", round(mean_accuracy,2)))) %>%
mutate(cell_value = ifelse(grepl("NA", cell_value), NA, cell_value)) %>%
select(-sd,-se, -mean_accuracy) %>%
pivot_wider(names_from = nesting_vars, values_from = "cell_value", names_sep = "-")
df_key <- suppressWarnings({tibble(col_keys = names(df)) %>%
filter(!grepl("locus", col_keys)) %>%
separate(col_keys, into = nesting_vars, sep = "-", remove = F) %>%
mutate_at(vars(contains("genotyper")), reformat_hla_genotyper) %>%
arrange_at(nesting_vars) %>%
mutate_all(as.character)
})
vline_var <- tail(nesting_vars,1)
vlines_sequence <- seq(1,nrow(df_key),by = length(unique(df_key[[vline_var]])))
df <- df %>%
select(locus, df_key$col_keys) %>%
flextable() %>%
colformat_char(na_str = "---") %>%
set_header_df(mapping = df_key, key = "col_keys") %>%
merge_h(part = "header") %>%
theme_vanilla() %>%
vline(j=vlines_sequence, border = fp_border_default()) %>%
fix_border_issues()
return(df)
Scratch work
subsample_cells_combined_df %>%
filter(field == "field_2") %>%
mutate(n_alleles = factor(n_alleles, levels = 0:2)) %>%
ggplot(aes(x = n_alleles, y = log10(n_cells)))+
geom_violin(scale = "width")+
geom_jitter(size = 0.2, height = 0, width =0.05, alpha = 0.2)+
# geom_boxplot(width=0.1)+
# ggbeeswarm::geom_beeswarm(size = 0.1, alpha = 0.1)+
coord_flip()+
facet_grid(genotyper ~ locus, scales = "free")+
theme_bw()
Coverage stats
subsample_cells_combined_df %>%
ggplot(aes(x = n_cells, y = coverage, color = genotyper)) +
geom_point() +
facet_wrap(genotyper ~ locus, scales = "free", nrow = 3) +
theme_bw() +
theme(strip.text = element_blank(),
axis.text.x = element_text(angle = 45, hjust = 1))+
scale_color_brewer(palette = "Dark2")
subsample_cells_combined_df %>%
select(-genotyper) %>% distinct() %>%
mutate(cov_per_cell = coverage/n_cells) %>%
ggplot(aes(x = log10(n_cells), y = cov_per_cell)) +
geom_point(color = "black", alpha = 0.1) +
stat_smooth(method = "lm")+
# stat_smooth()+
facet_wrap( ~ locus, scales = "free", nrow = 1) +
theme_bw() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))+
scale_color_brewer(palette = "Dark2")
subsample_cells_combined_df %>%
select(-genotyper) %>% distinct() %>%
filter(!is.na(n_cells)) %>%
mutate(cov_per_cell = coverage/n_cells) %>%
mutate(n_cells = cut(n_cells, seq(0,10000,by=2500), right = F)) %>%
ggplot(aes(x = n_cells, y = cov_per_cell)) +
stat_summary(fun = function(x) mean(x,na.rm=T), geom = "bar") +
# geom_point(color = "black", alpha = 0.1) +
# stat_smooth(method = "lm")+
# stat_smooth()+
facet_wrap( ~ locus, scales = "free", nrow = 1) +
theme_bw() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))+
scale_color_brewer(palette = "Dark2")
hist(cut(1:100, seq(1,100,10)))
subsample_cells_combined_df %>%
ungroup() %>%
count(genotyper, locus, field)
subsample_reads_combined_df %>%
ungroup() %>%
count(genotyper, locus, field)
LS0tCnRpdGxlOiAiMykgQ292ZXJhZ2UgQW5hbHlzaXMiCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiAzCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIGNvZGVfZm9sZGluZzogaGlkZQotLS0KCgojIFN0YXJ0dXAgCgpgYGB7ciwgbWVzc2FnZSA9IEZ9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGNvd3Bsb3QpCmxpYnJhcnkoZ2dwbWlzYykKCnNvdXJjZSgiZGF0YV9pbXBvcnRfZnVuY3Rpb25zLlIiKQpzb3VyY2UoImNhbGN1bGF0aW9uX2Z1bmN0aW9ucy5SIikKc291cmNlKCJmaWd1cmVfZm9ybWF0X2Z1bmN0aW9ucy5SIikKYWxsX2hsYV9leHBhbmRlZCA8LSByZWFkUkRTKCJhbGxfaGxhX2V4cGFuZGVkLlJEUyIpCmlzYl9wYXRoIDwtICIvbGFicy9raGF0cmlsYWIvc29sb21vbmIvY292aWQvaXNiIgppc2Jfc2FtcGxlcyA8LSByZWFkX3RzdigiL2xhYnMva2hhdHJpbGFiL3NvbG9tb25iL2NvdmlkL2lzYi9sb2dzLzIxMDIxN18yMzI3MjUvcGFyYWxsZWwubG9nIikgJT4lIAogIHNlcGFyYXRlKENvbW1hbmQsIGludG8gPSBjKE5BLCAic2FtcGxlIiksIHNlcCA9ICIgIikgJT4lIAogIHB1bGwoc2FtcGxlKSAlPiUgdW5pcXVlKCkKYGBgCgojIyMgR2V0IHJlZmVyZW5jZSBhbGxlbGVzCgotIEdDaDM4IHJlZmVyZW5jZSBhbGxlbGVzIChwZXIgaHR0cHM6Ly93d3cuZWJpLmFjLnVrL2lwZC9pbWd0L2hsYS9oZWxwL2dlbm9taWNzLmh0bWwpCi0gVG8gYmUgdXNlZCB0byBjYWxjdWxhdGUgY292ZXJhZ2UKCmBgYHtyLCBtZXNzYWdlID0gRn0KcmVmZXJlbmNlX2FsbGVsZXMgPC0gcmVhZF90c3YoIkdDaDM4X3JlZmVyZW5jZV9hbGxlbGVzLnR4dCIsIGNvbF9uYW1lcyA9IEYpICU+JSBwdWxsKDEpCmdlbm9tZV9yZWdpb25fcmVmZXJlbmNlIDwtIGdldF9hbGxlbGVfbGVuZ3RoKHJlZmVyZW5jZV9hbGxlbGVzKQpgYGAKCiMjIyBHZXQgYXJjYXNITEEgYWxpZ25tZW50IHN0YXRzCgpgYGB7cn0KYXJjYXNfbG9nX2RpciA8LSBzcHJpbnRmKCIlcy9hcmNhc0hMQSIsIGlzYl9wYXRoKQphbGlnbm1lbnRfc3RhdHNfZGYgPC0gaGxhX21hcHBpbmdfc3RhdHNfaW1wb3J0KGlzYl9zYW1wbGVzLCBhcmNhc19sb2dfZGlyKQpgYGAKCmBgYHtyfQpobGFfbWFwcGluZ19zdGF0c19pbXBvcnRfdjIgPC0gZnVuY3Rpb24oc2FtcGxlcywgbG9nX2Rpcil7CiAgdGliYmxlKHNhbXBsZSA9IHNhbXBsZXMpICU+JSAKICAgIG11dGF0ZShkYXRhID0gbWFwKHNhbXBsZSwgZnVuY3Rpb24oeCl7CiAgICAgIGxvZ19wYXRoIDwtIHNwcmludGYoIiVzLyVzLmdlbm90eXBlLmxvZyIsbG9nX2Rpcix4KQogICAgICBkZiA8LSB0aWJibGUobGluZXMgPSByZWFkX2xpbmVzKGxvZ19wYXRoKSkKICAgICAgaWYgKGFueShncmVwbCgiZXJyb3IiLCBkZiRsaW5lcywgaWdub3JlLmNhc2UgPSBUKSkpewogICAgICAgIE5BCiAgICAgIH0gZWxzZSB7CiAgICAgICAgdG90YWxfcmVhZHMgPC0gZGYgJT4lIAogICAgICAgICAgbXV0YXRlKGxpbmVzID0gZ3N1YigiXHQiLCAiIiwgbGluZXMpKSAlPiUgCiAgICAgICAgICBmaWx0ZXIoZ3JlcGwoIl5cXFthbGlnbm1lbnRcXF0gUHJvY2Vzc2VkIiwgbGluZXMpKSAlPiUKICAgICAgICAgIG11dGF0ZShsaW5lcyA9IGdzdWIoIlxcLC4qIiwgIiIsIGxpbmVzKSkgJT4lIAogICAgICAgICAgbXV0YXRlKGxpbmVzID0gc3RyX2V4dHJhY3QobGluZXMsICJbMC05XSsiKSkgJT4lIAogICAgICAgICAgcHVsbChsaW5lcykgJT4lIAogICAgICAgICAgYXMubnVtZXJpYygpCiAgICAgICAgZGYgJT4lIAogICAgICAgICAgbXV0YXRlKGxpbmVzID0gZ3N1YigiXHQiLCAiIiwgbGluZXMpKSAlPiUgCiAgICAgICAgICBmaWx0ZXIoZ3JlcGwoIl5ITEEiLCBsaW5lcykpICU+JSAKICAgICAgICAgIHNlcGFyYXRlKGxpbmVzLCBpbnRvID0gYygibG9jdXMiLCAiYWJ1bmRhbmNlIiwgInJlYWRzIiwgImNsYXNzZXMiKSwgc2VwID0gIiArIikgJT4lIAogICAgICAgICAgbXV0YXRlKHRvdGFsX3JlYWRzID0gdG90YWxfcmVhZHMpICU+JSAKICAgICAgICAgIG11dGF0ZSh0b3RhbF9obGFfcmVhZHMgPSBzdW0oYXMubnVtZXJpYyhyZWFkcykpKQogICAgICB9CiAgICB9KSkgJT4lCiAgICB1bm5lc3QoZGF0YSkgJT4lIAogICAgc2VsZWN0KCEoY29udGFpbnMoImRhdGEiKSkpICU+JSAKICAgIHNlcGFyYXRlKGxvY3VzLCBpbnRvID0gYyhOQSwgImxvY3VzIiksIHNlcCA9ICItIikgJT4lIAogICAgbXV0YXRlX2F0KGMoInJlYWRzIiwgImNsYXNzZXMiKSwgYXMubnVtZXJpYykKfQoKYXJjYXNfbG9nX2RpciA8LSBzcHJpbnRmKCIlcy9hcmNhc0hMQSIsIGlzYl9wYXRoKQphbGlnbm1lbnRfc3RhdHNfZGYgPC0gaGxhX21hcHBpbmdfc3RhdHNfaW1wb3J0X3YyKGlzYl9zYW1wbGVzLCBhcmNhc19sb2dfZGlyKSAlPiUgCiAgZmlsdGVyKGdyZXBsKCJeW0FCQ118XkRbUFFSXVtBQl0xIiwgbG9jdXMpICYgZ3JlcGwoIi0oQUN8QkwpJCIsIHNhbXBsZSkpJT4lIAogIG11dGF0ZShyZWFkcyA9IHRvdGFsX3JlYWRzKQphbGlnbm1lbnRfc3RhdHNfZGYgCmBgYAoKCgojIyMgSW1wb3J0IGNlbGwgY291bnRzCgpgYGB7cn0KY2VsbF9jb3VudHNfZGYgPC0gcmVhZFJEUygiaXNiX3NlcXVlbmNlZF9jZWxsX2NvdW50LlJEUyIpCmNlbGxfY291bnRzX2RmCmBgYAoKIyMjIEFzc2VtYmxlIGFjY3VyYWN5IERGCgpgYGB7cn0Kc3VjY2Vzc19kZiA8LSByZWFkUkRTKCJpc2Jfc3VjY2Vzcy5SRFMiKQphY2N1cmFjeV9kZiA8LSByZWFkUkRTKCJpc2JfYWNjdXJhY3lfZHJiMzQ1X2ZpbHRlcmVkLlJEUyIpCmFjY3VyYWN5X2RmIDwtIGFjY3VyYWN5X2RmICU+JSAKICBsZWZ0X2pvaW4oCiAgICBzdWNjZXNzX2RmICU+JSBzZWxlY3Qoc2FtcGxlOmZpZWxkLCBnZW5vdHlwZXIsIHN1Y2Nlc3MgPSBhY2N1cmFjeSksCiAgICBieSA9IGMoInNhbXBsZSIsICJsb2N1cyIsICJmaWVsZCIsICJnZW5vdHlwZXIiKQogICklPiUgCiAgbGVmdF9qb2luKGFsaWdubWVudF9zdGF0c19kZiwgYnkgPSBjKCJzYW1wbGUiLCAibG9jdXMiKSkgJT4lIAogIGxlZnRfam9pbihnZW5vbWVfcmVnaW9uX3JlZmVyZW5jZSwgYnkgPSAibG9jdXMiKSAlPiUKICBsZWZ0X2pvaW4oY2VsbF9jb3VudHNfZGYsIGJ5ID0gInNhbXBsZSIpICU+JQogIG11dGF0ZV9hdCh2YXJzKGMocmVhZHMsIGJwKSksIGFzLm51bWVyaWMpICU+JSAKICBtdXRhdGUoY292ZXJhZ2UgPSAocmVhZHMgKiA5MSkvYnApICU+JSAKICBtdXRhdGUobl9hbGxlbGVzID0gbWFwX2RibChhbGxlbGUsIGZ1bmN0aW9uKHgpIHN1bSghaXMubmEoeCkpKSkgJT4lIAogIGZpbHRlcihncmVwbCgiXltBQkNdfEQuW0FCXTEiLCBsb2N1cykgJiBncmVwbCgiLShBQ3xCTCkkIiwgc2FtcGxlKSAmIGdlbm90eXBlciAhPSAiaGxhbWluZXIiKSAKYWNjdXJhY3lfZGYKYGBgCgoKIyMjIENvdmVyYWdlIGJhc2VkIHBsb3RzCgpgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTIuNSwgd2FybmluZyA9IEYsIG1lc3NhZ2UgPSBGfQpnZ19jb3ZlcmFnZShhY2N1cmFjeV9kZiwgeF92YXIgPSAicmVhZHMiLCB5X3ZhciA9ICJhY2N1cmFjeSIpIApgYGAKYGBge3IsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD0yLjUsIHdhcm5pbmcgPSBGLCBtZXNzYWdlID0gRn0KZ2dfY292ZXJhZ2UoYWNjdXJhY3lfZGYsIHhfdmFyID0gImNvdmVyYWdlIiwgeV92YXIgPSAic3VjY2VzcyIpCmBgYApgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTMsIHdhcm5pbmcgPSBGLCBtZXNzYWdlID0gRn0KZ2dfY292ZXJhZ2UoYWNjdXJhY3lfZGYsIHhfdmFyID0gImNvdmVyYWdlIiwgeV92YXIgPSAibl9hbGxlbGVzIiwgZmFjZXRfZ2Vub3R5cGVyID0gVCkKYGBgCgojIyMgQ2VsbCBudW1iZXIgYmFzZWQgcGxvdHMKCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9Mi41LCB3YXJuaW5nID0gRiwgbWVzc2FnZSA9IEZ9CmdnX2NvdmVyYWdlKGFjY3VyYWN5X2RmLCB4X3ZhciA9ICJuX2NlbGxzIiwgeV92YXIgPSAiYWNjdXJhY3kiKSAKYGBgCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9Mi41LCB3YXJuaW5nID0gRiwgbWVzc2FnZSA9IEZ9CmdnX2NvdmVyYWdlKGFjY3VyYWN5X2RmLCB4X3ZhciA9ICJuX2NlbGxzIiwgeV92YXIgPSAic3VjY2VzcyIpCmBgYApgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTMsIHdhcm5pbmcgPSBGLCBtZXNzYWdlID0gRn0KZ2dfY292ZXJhZ2UoYWNjdXJhY3lfZGYsIHhfdmFyID0gIm5fY2VsbHMiLCB5X3ZhciA9ICJuX2FsbGVsZXMiLCBmYWNldF9nZW5vdHlwZXIgPSBUKQpgYGAKCgojIFN1YnNhbXBsZSBSRUFEUwoKIyMjIEltcG9ydCByZWFkIHN1YnNhbXBsZSBkYXRhCgpgYGB7cn0KIyBJbXBvcnQgcHJlZGljdGVkIGdlbm90eXBlcwpzdWJzYW1wbGVfcmVhZHNfcGF0aCA8LSAiL2xhYnMva2hhdHJpbGFiL3NvbG9tb25iL2NvdmlkL2lzYi9zdWJzYW1wbGUiCnN1YnNhbXBsZV9yZWFkc19zYW1wbGVzIDwtIHRpYmJsZShzYW1wbGUgPSBsaXN0LmZpbGVzKHNwcmludGYoIiVzL2FyY2FzSExBIiwgc3Vic2FtcGxlX3JlYWRzX3BhdGgpKSkgJT4lIAogIGZpbHRlcihncmVwbCgiXklOQ09WIiwgc2FtcGxlKSkgJT4lIAogIHNlcGFyYXRlKHNhbXBsZSwgaW50byA9IGMoInNhbXBsZSIpLCBzZXAgPSAiXFwuIiwgZXh0cmEgPSAiZHJvcCIpICU+JSAKICBkaXN0aW5jdCgpICU+JSAKICBwdWxsKHNhbXBsZSkKc3Vic2FtcGxlX3JlYWRzX2RmIDwtIGZvcm1hdF9obGFfdGFibGUoY29tYmluZV9ITEFfaW1wb3J0KHBhdGggPSBzdWJzYW1wbGVfcmVhZHNfcGF0aCwgc2FtcGxlcyA9IHN1YnNhbXBsZV9yZWFkc19zYW1wbGVzKSkKc3Vic2FtcGxlX3JlYWRzX2RmIDwtIHN1YnNhbXBsZV9yZWFkc19kZiAlPiUgCiAgZmlsdGVyKGdyZXBsKCJeW0FCQ118RC5bQUJdMSIsIGxvY3VzKSAmIGdyZXBsKCItKEFDfEJMKV8iLCBzYW1wbGUpKQpzdWJzYW1wbGVfcmVhZHNfZGYKYGBgCgpgYGB7ciwgbWVzc2FnZSA9IEZ9CiMgRXhwYW5kIGludml0cm8gZ2Vub3R5cGVzIGFjcm9zcyByZWFkIHN1YnNhbXBsZSBuYW1lcwppbnZpdHJvX2RmIDwtIGludml0cm9faW1wb3J0KCkKaW52aXRyb19yZWFkc19kZiA8LSBzdWJzYW1wbGVfcmVhZHNfZGYgJT4lIAogIHNlbGVjdChzYW1wbGUpICU+JSAKICBkaXN0aW5jdCgpICU+JSAKICBzZXBhcmF0ZShzYW1wbGUsIGludG8gPSBjKCJzYW1wbGUiLCAic3Vic2FtcGxlIiksIHNlcCA9ICJfIikgJT4lIAogIGxlZnRfam9pbihpbnZpdHJvX2RmLCBieSA9ICJzYW1wbGUiKSAlPiUgCiAgdW5pdGUoc2FtcGxlLCBzYW1wbGUsIHN1YnNhbXBsZSwgc2VwID0gIl8iKSAlPiUgCiAgZm9ybWF0X2hsYV90YWJsZSgpICU+JSAKICBkcm9wX25hKCkKaW52aXRyb19yZWFkc19kZgpgYGAKCmBgYHtyfQojIEltcG9ydCByZWFkIHN0YXRpc3RpY3MKc3Vic2FtcGxlX3JlYWRzX2FyY2FzX2xvZ19kaXIgPC0gc3ByaW50ZigiJXMvYXJjYXNITEEiLCBzdWJzYW1wbGVfcmVhZHNfcGF0aCkKc3Vic2FtcGxlX3JlYWRzX2FsaWdubWVudF9zdGF0c19kZiA8LSBobGFfbWFwcGluZ19zdGF0c19pbXBvcnQoc3Vic2FtcGxlX3JlYWRzX3NhbXBsZXMsIHN1YnNhbXBsZV9yZWFkc19hcmNhc19sb2dfZGlyKQpgYGAKCmBgYHtyfQojIEltcG9ydCByZWFkIHN0YXRpc3RpY3MKc3Vic2FtcGxlX3JlYWRzX2FyY2FzX2xvZ19kaXIgPC0gc3ByaW50ZigiJXMvYXJjYXNITEEiLCBzdWJzYW1wbGVfcmVhZHNfcGF0aCkKc3Vic2FtcGxlX3JlYWRzX2FsaWdubWVudF9zdGF0c19kZiA8LSBobGFfbWFwcGluZ19zdGF0c19pbXBvcnRfdjIoc3Vic2FtcGxlX3JlYWRzX3NhbXBsZXMsIHN1YnNhbXBsZV9yZWFkc19hcmNhc19sb2dfZGlyKQpzdWJzYW1wbGVfcmVhZHNfYWxpZ25tZW50X3N0YXRzX2RmIDwtIHN1YnNhbXBsZV9yZWFkc19hbGlnbm1lbnRfc3RhdHNfZGYgJT4lIAogIG11dGF0ZShyZWFkcyA9IHRvdGFsX3JlYWRzKQpzdWJzYW1wbGVfcmVhZHNfYWxpZ25tZW50X3N0YXRzX2RmCmBgYAoKCiMjIyBDYWxjdWxhdGUgYWNjdXJhY3kKCmBgYHtyfQojIENhbGN1bGF0ZSBhY2N1cmFjeQpzdWJzYW1wbGVfcmVhZHNfYWNjdXJhY3lfZGYgPC0gY29tcGFyZV9obGEoCiAgaGxhX2RmID0gYmluZF9yb3dzKAogICAgc3Vic2FtcGxlX3JlYWRzX2RmLAogICAgaW52aXRyb19yZWFkc19kZgogICksCiAgcmVmZXJlbmNlID0gImludml0cm8iLCAKICBtZXRob2QgPSAiYWNjdXJhY3kiCikKIyBzYXZlUkRTKHN1YnNhbXBsZV9yZWFkc19hY2N1cmFjeV9kZiwgImlzYl9zdWJzYW1wbGVfcmVhZHNfYWNjdXJhY3kuUkRTIikKYGBgCgoKYGBge3J9CiMgQ2FsY3VsYXRlIHN1Y2Nlc3MKc3Vic2FtcGxlX3JlYWRzX3N1Y2Nlc3NfZGYgPC0gY29tcGFyZV9obGEoCiAgaGxhX2RmID0gYmluZF9yb3dzKAogICAgc3Vic2FtcGxlX3JlYWRzX2RmLAogICAgaW52aXRyb19yZWFkc19kZgogICksCiAgcmVmZXJlbmNlID0gImludml0cm8iLCAKICBtZXRob2QgPSAic3VjY2VzcyIKKQojIHNhdmVSRFMoc3Vic2FtcGxlX3JlYWRzX3N1Y2Nlc3NfZGYsICJpc2Jfc3Vic2FtcGxlX3JlYWRzX3N1Y2Nlc3MuUkRTIikKYGBgCgpgYGB7cn0Kc3Vic2FtcGxlX3JlYWRzX2FjY3VyYWN5X2RmIDwtIHJlYWRSRFMoImlzYl9zdWJzYW1wbGVfcmVhZHNfYWNjdXJhY3kuUkRTIikKc3Vic2FtcGxlX3JlYWRzX3N1Y2Nlc3NfZGYgPC0gcmVhZFJEUygiaXNiX3N1YnNhbXBsZV9yZWFkc19zdWNjZXNzLlJEUyIpCmBgYAoKCgpgYGB7cn0KIyBDb21iaW5lIHZhcmlvdXMgZGF0YQpzdWJzYW1wbGVfcmVhZHNfY29tYmluZWRfZGYgPC0gc3Vic2FtcGxlX3JlYWRzX2FjY3VyYWN5X2RmICU+JSAKICBsZWZ0X2pvaW4oCiAgICBzdWJzYW1wbGVfcmVhZHNfc3VjY2Vzc19kZiAlPiUgc2VsZWN0KHNhbXBsZTpmaWVsZCwgZ2Vub3R5cGVyLCBzdWNjZXNzID0gYWNjdXJhY3kpLAogICAgYnkgPSBjKCJzYW1wbGUiLCAibG9jdXMiLCAiZmllbGQiLCAiZ2Vub3R5cGVyIikKICApJT4lIAogIGxlZnRfam9pbihzdWJzYW1wbGVfcmVhZHNfYWxpZ25tZW50X3N0YXRzX2RmLCBieSA9IGMoInNhbXBsZSIsICJsb2N1cyIpKSAlPiUgCiAgbGVmdF9qb2luKGdlbm9tZV9yZWdpb25fcmVmZXJlbmNlLCBieSA9ICJsb2N1cyIpICU+JQogIGJpbmRfcm93cyhhY2N1cmFjeV9kZiAlPiUgc2VsZWN0KC1uX2NlbGxzKSkgJT4lICMgTm8gY2VsbCBudW1iZXJzIGZvciByZWFkIHN1YnNhbXBsZXMKICBtdXRhdGVfYXQodmFycyhjKHJlYWRzLCBicCkpLCBhcy5udW1lcmljKSAlPiUgCiAgbXV0YXRlKGNvdmVyYWdlID0gKHJlYWRzICogOTEpL2JwKSAlPiUgICMgQ2FsY3VsYXRlIGNvdmVyYWdlCiAgbXV0YXRlKG5fYWxsZWxlcyA9IG1hcF9kYmwoYWxsZWxlLCBmdW5jdGlvbih4KSBzdW0oIWlzLm5hKHgpKSkpICU+JSAgIyBDYWxjdWxhdGUgbl9hbGxlbGVzCiAgZmlsdGVyKGdyZXBsKCJeW0FCQ118RC5bQUJdMSIsIGxvY3VzKSAmIGdyZXBsKCItKEFDfEJMKSIsIHNhbXBsZSkgJiBnZW5vdHlwZXIgIT0gImhsYW1pbmVyIikgCmBgYAoKIyMjIFJlYWRzIHBsb3RzCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9Mi41LCB3YXJuaW5nID0gRiwgbWVzc2FnZSA9IEZ9CmdnX2NvdmVyYWdlKHN1YnNhbXBsZV9yZWFkc19jb21iaW5lZF9kZiwgeF92YXIgPSAicmVhZHMiLCB5X3ZhciA9ICJhY2N1cmFjeSIpIApwbHRfcmVhZF9hY2N1cmFjeV9hbGwgPC0gZ2dfY292ZXJhZ2Uoc3Vic2FtcGxlX3JlYWRzX2NvbWJpbmVkX2RmLCB4X3ZhciA9ICJyZWFkcyIsIHlfdmFyID0gImFjY3VyYWN5IikgCnBsdF9yZWFkX2FjY3VyYWN5X2FiYyA8LSBnZ19jb3ZlcmFnZShzdWJzYW1wbGVfcmVhZHNfY29tYmluZWRfZGYgJT4lIGZpbHRlcihncmVwbCgiXltBQkNdIiwgbG9jdXMpKSwgeF92YXIgPSAicmVhZHMiLCB5X3ZhciA9ICJhY2N1cmFjeSIpIApgYGAKYGBge3IsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD0yLjUsIHdhcm5pbmcgPSBGLCBtZXNzYWdlID0gRn0KZ2dfY292ZXJhZ2Uoc3Vic2FtcGxlX3JlYWRzX2NvbWJpbmVkX2RmLCB4X3ZhciA9ICJyZWFkcyIsIHlfdmFyID0gInN1Y2Nlc3MiKQpwbHRfcmVhZF9zdWNjZXNzX2FsbCA8LSBnZ19jb3ZlcmFnZShzdWJzYW1wbGVfcmVhZHNfY29tYmluZWRfZGYsIHhfdmFyID0gInJlYWRzIiwgeV92YXIgPSAic3VjY2VzcyIpCnBsdF9yZWFkX3N1Y2Nlc3NfYWJjIDwtIGdnX2NvdmVyYWdlKHN1YnNhbXBsZV9yZWFkc19jb21iaW5lZF9kZiAlPiUgZmlsdGVyKGdyZXBsKCJeW0FCQ10iLCBsb2N1cykpLCB4X3ZhciA9ICJyZWFkcyIsIHlfdmFyID0gInN1Y2Nlc3MiKSAKYGBgCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9Mywgd2FybmluZyA9IEYsIG1lc3NhZ2UgPSBGfQpnZ19jb3ZlcmFnZShzdWJzYW1wbGVfcmVhZHNfY29tYmluZWRfZGYsIHhfdmFyID0gInJlYWRzIiwgeV92YXIgPSAibl9hbGxlbGVzIiwgZmFjZXRfZ2Vub3R5cGVyID0gVCkKcGx0X3JlYWRfYWxsZWxlX2FsbCA8LSBnZ19jb3ZlcmFnZShzdWJzYW1wbGVfcmVhZHNfY29tYmluZWRfZGYsIHhfdmFyID0gInJlYWRzIiwgeV92YXIgPSAibl9hbGxlbGVzIiwgZmFjZXRfZ2Vub3R5cGVyID0gVCkKcGx0X3JlYWRfYWxsZWxlX2FiYyA8LSBnZ19jb3ZlcmFnZShzdWJzYW1wbGVfcmVhZHNfY29tYmluZWRfZGYgJT4lIGZpbHRlcihncmVwbCgiXltBQkNdIiwgbG9jdXMpKSwgeF92YXIgPSAicmVhZHMiLCB5X3ZhciA9ICJuX2FsbGVsZXMiLCBmYWNldF9nZW5vdHlwZXIgPSBUKQpgYGAKLSBEZWZhdWx0IGFyY2FzSExBIGN1dCBvZmYgNzUgcmVhZHMgKGxvZzEwID0gMS44KQoKYGBge3IsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD0zLCB3YXJuaW5nID0gRiwgbWVzc2FnZSA9IEZ9CnN1YnNhbXBsZV9yZWFkc19jb21iaW5lZF9kZiAlPiUgCiAgZmlsdGVyKGZpZWxkID09ICJmaWVsZF8yIikgJT4lIAogIG11dGF0ZShuX2FsbGVsZXMgPSBmYWN0b3Iobl9hbGxlbGVzLCBsZXZlbHMgPSAwOjIpKSAlPiUgCiAgZ2dwbG90KGFlcyh5ID0gbl9hbGxlbGVzLCB4ID0gbG9nMTAoY292ZXJhZ2UpKSkrCiAgIyBnZW9tX3Zpb2xpbihzY2FsZSA9ICJjb3VudCIsIGFscGhhID0gMC41LCApKwogIGdlb21faml0dGVyKHNpemUgPSAwLjIsIHdpZHRoID0gMCwgaGVpZ2h0ID0wLjIsIGFscGhhID0gMC4yKSsKICAjIGdlb21fYm94cGxvdCh3aWR0aD0wLjEpKwogICMgZ2diZWVzd2FybTo6Z2VvbV9iZWVzd2FybShzaXplID0gMC4xLCBhbHBoYSA9IDAuMSkrCiAgIyBjb29yZF9mbGlwKCkrCiAgZmFjZXRfZ3JpZChnZW5vdHlwZXIgfiBsb2N1cywgc2NhbGVzID0gImZyZWUiKSsKICB0aGVtZV9idygpCmBgYAoKIyBTdWJzYW1wbGUgQ0VMTFMKCmBgYHtyfQojIEltcG9ydCBwcmVkaWN0ZWQgZ2Vub3R5cGVzCnN1YnNhbXBsZV9jZWxsc19wYXRoIDwtICIvbGFicy9raGF0cmlsYWIvc29sb21vbmIvY292aWQvaXNiL3N1YnNhbXBsZV9jZWxscyIKc3Vic2FtcGxlX2NlbGxzX3NhbXBsZXMgPC0gdGliYmxlKHNhbXBsZSA9IGxpc3QuZmlsZXMoc3ByaW50ZigiJXMvYXJjYXNITEEiLCBzdWJzYW1wbGVfY2VsbHNfcGF0aCkpKSAlPiUgCiAgZmlsdGVyKGdyZXBsKCJeSU5DT1YiLCBzYW1wbGUpKSAlPiUgCiAgc2VwYXJhdGUoc2FtcGxlLCBpbnRvID0gYygic2FtcGxlIiksIHNlcCA9ICJcXC4iLCBleHRyYSA9ICJkcm9wIikgJT4lIAogIGRpc3RpbmN0KCkgJT4lIAogIHB1bGwoc2FtcGxlKQpzdWJzYW1wbGVfY2VsbHNfZGYgPC0gZm9ybWF0X2hsYV90YWJsZShjb21iaW5lX0hMQV9pbXBvcnQocGF0aCA9IHN1YnNhbXBsZV9jZWxsc19wYXRoLCBzYW1wbGVzID0gc3Vic2FtcGxlX2NlbGxzX3NhbXBsZXMpKQpzdWJzYW1wbGVfY2VsbHNfZGYgPC0gc3Vic2FtcGxlX2NlbGxzX2RmICU+JSAKICBmaWx0ZXIoZ3JlcGwoIl5bQUJDXXxELltBQl0xIiwgbG9jdXMpICYgZ3JlcGwoIi0oQUN8QkwpXyIsIHNhbXBsZSkpCnN1YnNhbXBsZV9jZWxsc19kZgpgYGAKCgpgYGB7ciwgbWVzc2FnZSA9IEZ9CiMgRXhwYW5kIGludml0cm8gZ2Vub3R5cGVzIGFjcm9zcyByZWFkIHN1YnNhbXBsZSBuYW1lcwppbnZpdHJvX2RmIDwtIGludml0cm9faW1wb3J0KCkKaW52aXRyb19jZWxsc19kZiA8LSBzdWJzYW1wbGVfY2VsbHNfZGYgJT4lIAogIHNlbGVjdChzYW1wbGUpICU+JSAKICBkaXN0aW5jdCgpICU+JSAKICBzZXBhcmF0ZShzYW1wbGUsIGludG8gPSBjKCJzYW1wbGUiLCAic3Vic2FtcGxlIiksIHNlcCA9ICJfIikgJT4lIAogIGxlZnRfam9pbihpbnZpdHJvX2RmLCBieSA9ICJzYW1wbGUiKSAlPiUgCiAgdW5pdGUoc2FtcGxlLCBzYW1wbGUsIHN1YnNhbXBsZSwgc2VwID0gIl8iKSAlPiUgCiAgZm9ybWF0X2hsYV90YWJsZSgpICU+JSAKICBkcm9wX25hKCkKaW52aXRyb19jZWxsc19kZgpgYGAKCmBgYHtyfQojIEltcG9ydCByZWFkIHN0YXRpc3RpY3MKc3Vic2FtcGxlX2NlbGxzX2FyY2FzX2xvZ19kaXIgPC0gc3ByaW50ZigiJXMvYXJjYXNITEEiLCBzdWJzYW1wbGVfY2VsbHNfcGF0aCkKc3Vic2FtcGxlX2NlbGxzX2FsaWdubWVudF9zdGF0c19kZiA8LSBobGFfbWFwcGluZ19zdGF0c19pbXBvcnQoc3Vic2FtcGxlX2NlbGxzX3NhbXBsZXMsIHN1YnNhbXBsZV9jZWxsc19hcmNhc19sb2dfZGlyKQpgYGAKCmBgYHtyfQojIEltcG9ydCBjZWxsIGNvdW50cyBmb3IgZWFjaCBzdWJzYW1wbGUKc3Vic2FtcGxlX2NlbGxfY291bnRzX2RmIDwtIHRpYmJsZShsaW5lID0gc3lzdGVtKCJ3YyAtbCAvbGFicy9raGF0cmlsYWIvc29sb21vbmIvY292aWQvaXNiL3N1YnNhbXBsZV9jZWxscy9iYXJjb2Rlcy9JTkNPVioiLCBpbnRlcm4gPSBUKSkgJT4lIAogIHNlcGFyYXRlKGxpbmUsIGludG8gPSBjKCJuX2NlbGxzIiwgImZpbGUiKSwgc2VwID0gIiAvIikgJT4lIAogIGRyb3BfbmEoKSAlPiUgCiAgbXV0YXRlKHNhbXBsZSA9IGdzdWIoIlxcLi4qIiwiIixiYXNlbmFtZShmaWxlKSkpICU+JSAKICBzZWxlY3QoLWZpbGUpICU+JSAKICBzZXBhcmF0ZShzYW1wbGUsIGludG8gPSBjKCJzYW1wbGUiLCAic3Vic2V0IiksIHNlcCA9ICJfIikKc3Vic2FtcGxlX2NlbGxfY291bnRzX2RmCmBgYAoKIyMjIENhbGN1bGF0ZSBhY2N1cmFjeQoKYGBge3J9CiMgQ2FsY3VsYXRlIGFjY3VyYWN5CnN1YnNhbXBsZV9jZWxsc19hY2N1cmFjeV9kZiA8LSBjb21wYXJlX2hsYSgKICBobGFfZGYgPSBiaW5kX3Jvd3MoCiAgICBzdWJzYW1wbGVfY2VsbHNfZGYsCiAgICBpbnZpdHJvX2NlbGxzX2RmCiAgKSwKICByZWZlcmVuY2UgPSAiaW52aXRybyIsIAogIG1ldGhvZCA9ICJhY2N1cmFjeSIKKQojIHNhdmVSRFMoc3Vic2FtcGxlX2NlbGxzX2FjY3VyYWN5X2RmLCAiaXNiX3N1YnNhbXBsZV9jZWxsc19hY2N1cmFjeS5SRFMiKQpgYGAKCmBgYHtyfQojIENhbGN1bGF0ZSBzdWNjZXNzCnN1YnNhbXBsZV9jZWxsc19zdWNjZXNzX2RmIDwtIGNvbXBhcmVfaGxhKAogIGhsYV9kZiA9IGJpbmRfcm93cygKICAgIHN1YnNhbXBsZV9jZWxsc19kZiwKICAgIGludml0cm9fY2VsbHNfZGYKICApLAogIHJlZmVyZW5jZSA9ICJpbnZpdHJvIiwgCiAgbWV0aG9kID0gInN1Y2Nlc3MiCikKIyBzYXZlUkRTKHN1YnNhbXBsZV9jZWxsc19zdWNjZXNzX2RmLCAiaXNiX3N1YnNhbXBsZV9jZWxsc19zdWNjZXNzLlJEUyIpCmBgYAoKYGBge3J9CiMgQ29tYmluZSB2YXJpb3VzIGRhdGEKc3Vic2FtcGxlX2NlbGxzX2NvbWJpbmVkX2RmIDwtIHN1YnNhbXBsZV9jZWxsc19hY2N1cmFjeV9kZiAlPiUgCiAgbGVmdF9qb2luKAogICAgc3Vic2FtcGxlX2NlbGxzX3N1Y2Nlc3NfZGYgJT4lIHNlbGVjdChzYW1wbGU6ZmllbGQsIGdlbm90eXBlciwgc3VjY2VzcyA9IGFjY3VyYWN5KSwKICAgIGJ5ID0gYygic2FtcGxlIiwgImxvY3VzIiwgImZpZWxkIiwgImdlbm90eXBlciIpCiAgKSU+JSAKICBsZWZ0X2pvaW4oc3Vic2FtcGxlX2NlbGxzX2FsaWdubWVudF9zdGF0c19kZiwgYnkgPSBjKCJzYW1wbGUiLCAibG9jdXMiKSkgJT4lIAogIGxlZnRfam9pbihnZW5vbWVfcmVnaW9uX3JlZmVyZW5jZSwgYnkgPSAibG9jdXMiKSAlPiUKICBsZWZ0X2pvaW4oY2VsbF9jb3VudHNfZGYsIGJ5ID0gInNhbXBsZSIpICU+JQogIGJpbmRfcm93cyhhY2N1cmFjeV9kZikgJT4lIAogIG11dGF0ZV9hdCh2YXJzKGMocmVhZHMsIGJwKSksIGFzLm51bWVyaWMpICU+JSAKICBtdXRhdGUoY292ZXJhZ2UgPSAocmVhZHMgKiA5MSkvYnApICU+JSAKICBtdXRhdGUobl9hbGxlbGVzID0gbWFwX2RibChhbGxlbGUsIGZ1bmN0aW9uKHgpIHN1bSghaXMubmEoeCkpKSkgJT4lIAogIGZpbHRlcihncmVwbCgiXltBQkNdfEQuW0FCXTEiLCBsb2N1cykgJiBncmVwbCgiLShBQ3xCTCkiLCBzYW1wbGUpICYgZ2Vub3R5cGVyICE9ICJobGFtaW5lciIpIApgYGAKCiMjIyBDb3ZlcmFnZSBwbG90cwoKYGBge3IsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD0yLjUsIHdhcm5pbmcgPSBGLCBtZXNzYWdlID0gRn0KZ2dfY292ZXJhZ2Uoc3Vic2FtcGxlX2NlbGxzX2NvbWJpbmVkX2RmLCB4X3ZhciA9ICJjb3ZlcmFnZSIsIHlfdmFyID0gImFjY3VyYWN5IikgCmBgYApgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTIuNSwgd2FybmluZyA9IEYsIG1lc3NhZ2UgPSBGfQpnZ19jb3ZlcmFnZShzdWJzYW1wbGVfY2VsbHNfY29tYmluZWRfZGYsIHhfdmFyID0gImNvdmVyYWdlIiwgeV92YXIgPSAic3VjY2VzcyIpCmBgYApgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTMsIHdhcm5pbmcgPSBGLCBtZXNzYWdlID0gRn0KZ2dfY292ZXJhZ2Uoc3Vic2FtcGxlX2NlbGxzX2NvbWJpbmVkX2RmLCB4X3ZhciA9ICJjb3ZlcmFnZSIsIHlfdmFyID0gIm5fYWxsZWxlcyIsIGZhY2V0X2dlbm90eXBlciA9IFQpCmBgYAoKIyMjIENlbGwgbnVtYmVyIHBsb3RzCgpgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTIuNSwgd2FybmluZyA9IEYsIG1lc3NhZ2UgPSBGfQpnZ19jb3ZlcmFnZShzdWJzYW1wbGVfY2VsbHNfY29tYmluZWRfZGYsIHhfdmFyID0gIm5fY2VsbHMiLCB5X3ZhciA9ICJhY2N1cmFjeSIpIApwbHRfY2VsbF9hY2N1cmFjeV9hbGwgPC0gZ2dfY292ZXJhZ2Uoc3Vic2FtcGxlX2NlbGxzX2NvbWJpbmVkX2RmLCB4X3ZhciA9ICJuX2NlbGxzIiwgeV92YXIgPSAiYWNjdXJhY3kiKSAKcGx0X2NlbGxfYWNjdXJhY3lfYWJjIDwtIGdnX2NvdmVyYWdlKHN1YnNhbXBsZV9jZWxsc19jb21iaW5lZF9kZiAlPiUgZmlsdGVyKGdyZXBsKCJeW0FCQ10iLCBsb2N1cykpLCB4X3ZhciA9ICJuX2NlbGxzIiwgeV92YXIgPSAiYWNjdXJhY3kiKSAKYGBgCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9Mi41LCB3YXJuaW5nID0gRiwgbWVzc2FnZSA9IEZ9CmdnX2NvdmVyYWdlKHN1YnNhbXBsZV9jZWxsc19jb21iaW5lZF9kZiwgeF92YXIgPSAibl9jZWxscyIsIHlfdmFyID0gInN1Y2Nlc3MiKSAKcGx0X2NlbGxfc3VjY2Vzc19hbGwgPC0gZ2dfY292ZXJhZ2Uoc3Vic2FtcGxlX2NlbGxzX2NvbWJpbmVkX2RmLCB4X3ZhciA9ICJuX2NlbGxzIiwgeV92YXIgPSAic3VjY2VzcyIpIApwbHRfY2VsbF9zdWNjZXNzX2FiYyA8LSBnZ19jb3ZlcmFnZShzdWJzYW1wbGVfY2VsbHNfY29tYmluZWRfZGYgJT4lIGZpbHRlcihncmVwbCgiXltBQkNdIiwgbG9jdXMpKSwgeF92YXIgPSAibl9jZWxscyIsIHlfdmFyID0gInN1Y2Nlc3MiKSAKYGBgCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9Mywgd2FybmluZyA9IEYsIG1lc3NhZ2UgPSBGfQpnZ19jb3ZlcmFnZShzdWJzYW1wbGVfY2VsbHNfY29tYmluZWRfZGYsIHhfdmFyID0gIm5fY2VsbHMiLCB5X3ZhciA9ICJuX2FsbGVsZXMiLCBmYWNldF9nZW5vdHlwZXIgPSBUKQpwbHRfY2VsbF9hbGxlbGVfYWxsIDwtIGdnX2NvdmVyYWdlKHN1YnNhbXBsZV9jZWxsc19jb21iaW5lZF9kZiwgeF92YXIgPSAibl9jZWxscyIsIHlfdmFyID0gIm5fYWxsZWxlcyIsIGZhY2V0X2dlbm90eXBlciA9IFQpCnBsdF9jZWxsX2FsbGVsZV9hYmMgPC0gZ2dfY292ZXJhZ2Uoc3Vic2FtcGxlX2NlbGxzX2NvbWJpbmVkX2RmICU+JSBmaWx0ZXIoZ3JlcGwoIl5bQUJDXSIsIGxvY3VzKSksIHhfdmFyID0gIm5fY2VsbHMiLCB5X3ZhciA9ICJuX2FsbGVsZXMiLCBmYWNldF9nZW5vdHlwZXIgPSBUKQpgYGAKCiMgQ29tYmluZWQgcGxvdHMKYGBge3IsIGZpZy53aWR0aCA9IDksIGZpZy5oZWlnaHQgPSA3LCBtZXNzYWdlID0gRiwgd2FybmluZyA9IEZ9Cm5vX2xlZyA8LSBsaXN0KHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikpCmxlZ2VuZCA8LSBjb3dwbG90OjpnZXRfbGVnZW5kKHBsdF9yZWFkX2FjY3VyYWN5X2FiYykKcGxvdF9ncmlkKAogIHBsb3RfZ3JpZCgKICAgIHBsdF9yZWFkX2FjY3VyYWN5X2FiYyArIG5vX2xlZywKICAgIHBsdF9yZWFkX3N1Y2Nlc3NfYWJjICsgbm9fbGVnLAogICAgcGx0X3JlYWRfYWxsZWxlX2FiYywKICAgIG5jb2wgPSAxLAogICAgYWxpZ24gPSAidiIsCiAgICBheGlzID0gImxyIiwKICAgIHJlbF9oZWlnaHRzID0gYygxLDEsMS4yKSwKICAgIGxhYmVscyA9IExFVFRFUlNbMTozXQogICksCiAgcGxvdF9ncmlkKAogICAgcGx0X2NlbGxfYWNjdXJhY3lfYWJjICsgbm9fbGVnLAogICAgcGx0X2NlbGxfc3VjY2Vzc19hYmMgKyBub19sZWcsCiAgICBwbHRfY2VsbF9hbGxlbGVfYWJjLAogICAgbmNvbCA9IDEsCiAgICBhbGlnbiA9ICJ2IiwKICAgIGF4aXMgPSAibHIiLAogICAgcmVsX2hlaWdodHMgPSBjKDEsMSwxLjIpLAogICAgbGFiZWxzID0gTEVUVEVSU1s0OjZdCiAgKSwKICBwbG90X2dyaWQoCiAgICBsZWdlbmQsCiAgICBsZWdlbmQsCiAgICBOQSwKICAgIG5jb2wgPSAxCiAgKSwKICBucm93ID0gMSwKICByZWxfd2lkdGhzID0gYygxLDEsMC4yNSkKKQpgYGAKCmBgYHtyLCBmaWcud2lkdGggPSAxOCwgZmlnLmhlaWdodCA9IDcsIG1lc3NhZ2UgPSBGLCB3YXJuaW5nID0gRn0Kbm9fbGVnIDwtIGxpc3QodGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSkKbGVnZW5kIDwtIGNvd3Bsb3Q6OmdldF9sZWdlbmQocGx0X3JlYWRfYWNjdXJhY3lfYWxsKQpwbG90X2dyaWQoCiAgcGxvdF9ncmlkKAogICAgcGx0X3JlYWRfYWNjdXJhY3lfYWxsICsgbm9fbGVnLAogICAgcGx0X3JlYWRfc3VjY2Vzc19hbGwgKyBub19sZWcsCiAgICBwbHRfcmVhZF9hbGxlbGVfYWxsLAogICAgbmNvbCA9IDEsCiAgICBhbGlnbiA9ICJ2IiwKICAgIGF4aXMgPSAibHIiLAogICAgcmVsX2hlaWdodHMgPSBjKDEsMSwxLjIpLAogICAgbGFiZWxzID0gTEVUVEVSU1sxOjNdCiAgKSwKICBwbG90X2dyaWQoCiAgICBwbHRfY2VsbF9hY2N1cmFjeV9hbGwgKyBub19sZWcsCiAgICBwbHRfY2VsbF9zdWNjZXNzX2FsbCArIG5vX2xlZywKICAgIHBsdF9jZWxsX2FsbGVsZV9hbGwsCiAgICBuY29sID0gMSwKICAgIGFsaWduID0gInYiLAogICAgYXhpcyA9ICJsciIsCiAgICByZWxfaGVpZ2h0cyA9IGMoMSwxLDEuMiksCiAgICBsYWJlbHMgPSBMRVRURVJTWzQ6Nl0KICApLAogIHBsb3RfZ3JpZCgKICAgIGxlZ2VuZCwKICAgIGxlZ2VuZCwKICAgIE5BLAogICAgbmNvbCA9IDEKICApLAogIG5yb3cgPSAxLAogIHJlbF93aWR0aHMgPSBjKDEsMSwwLjI1KQopCmBgYAoKIyBTbG9wZSBzdGF0cwoKYGBge3J9CmdldF9sbV9zdGF0cyA8LSBmdW5jdGlvbihkZiwgeF92YXIgPSAiY292ZXJhZ2UiLCB5X3ZhciA9ICJhY2N1cmFjeSIsIGZpZWxkX3ZhciA9ICJmaWVsZF8yIiwgeF9sb2cgPSBUKXsKICAjIElucHV0IGNoZWNrcwogIGFyZ19jb2wgPC0gbWFrZUFzc2VydENvbGxlY3Rpb24oKQogIGFzc2VydENob2ljZSh5X3ZhciwgYygiYWNjdXJhY3kiLCAic3VjY2VzcyIsICJuX2FsbGVsZXMiKSwgYWRkID0gYXJnX2NvbCkKICBhc3NlcnRDaG9pY2UoeF92YXIsIGMoInJlYWRzIiwgImNvdmVyYWdlIiwgIm5fY2VsbHMiKSwgYWRkID0gYXJnX2NvbCkKICBhc3NlcnRDaG9pY2UoZmllbGRfdmFyLCBjKCJmaWVsZF8xIiwgImZpZWxkXzIiLCAiZmllbGRfMyIpLCBhZGQgPSBhcmdfY29sKQogIGFzc2VydExvZ2ljYWwoeF9sb2csIGFkZCA9IGFyZ19jb2wpCiAgaWYgKGFyZ19jb2wkaXNFbXB0eSgpPT1GKSB7bWFwKGFyZ19jb2wkZ2V0TWVzc2FnZXMoKSxwcmludCk7cmVwb3J0QXNzZXJ0aW9ucyhhcmdfY29sKX0KICAKICAjIGJyb3dzZXIoKQogIGRmIDwtIGRmICU+JSAKICAgIGZpbHRlcihmaWVsZCA9PSBmaWVsZF92YXIpICU+JSAKICAgIHJlbW92ZV9pbnZhbGlkX2NvbWJpbmF0aW9ucygpCiAgaWYgKHhfbG9nID09VCl7ZGYgPC0gZGYgJT4lIG11dGF0ZV9hdCh4X3ZhciwgbG9nMTApfQogIGRmICU+JQogIGZpbHRlcl9hdCh4X3ZhciwgZnVuY3Rpb24oeCkgIWlzLm5hKHgpICYgIWlzLmluZmluaXRlKHgpKSAlPiUgCiAgZ3JvdXBfYnkobG9jdXMsIGZpZWxkLCBnZW5vdHlwZXIpICU+JQogIG5lc3QoKSAlPiUKICBtdXRhdGUoZGF0YSA9IG1hcChkYXRhLCBmdW5jdGlvbih4KXsKICAgIHN1bW1hcnkobG0oISFzeW0oeV92YXIpIH4gISFzeW0oeF92YXIpLCBkYXRhID0geCkpICU+JSBicm9vbTo6dGlkeSgpICU+JSBmaWx0ZXIodGVybSA9PSB4X3ZhcikKICB9KSkgJT4lIHVubmVzdF93aWRlcihkYXRhKSAlPiUKICBtdXRhdGUoZXN0X21pbiA9IHJvdW5kKGVzdGltYXRlIC0gMipzdGQuZXJyb3IsIDIpLAogICAgICAgICBlc3RfbWF4ID0gcm91bmQoZXN0aW1hdGUgKyAyKnN0ZC5lcnJvciwgMikpCn0KCm1vZGVsX3N0YXRzIDwtIGdldF9sbV9zdGF0cyhzdWJzYW1wbGVfY2VsbHNfY29tYmluZWRfZGYsIHhfdmFyID0gInJlYWRzIiwgeV92YXIgPSAiYWNjdXJhY3kiLCB4X2xvZyA9IFQpCm1vZGVsX3N0YXRzCmBgYAoKYGBge3J9Cm1vZGVsX3N0YXRzIDwtIGJpbmRfcm93cygKICBnZXRfbG1fc3RhdHMoc3Vic2FtcGxlX3JlYWRzX2NvbWJpbmVkX2RmLCB4X3ZhciA9ICJyZWFkcyIsIHlfdmFyID0gImFjY3VyYWN5IiwgeF9sb2cgPSBUKSAlPiUgbXV0YXRlKHhfdmFyID0gInJlYWRzIiwgeV92YXIgPSAiYWNjdXJhY3kiKSwKICBnZXRfbG1fc3RhdHMoc3Vic2FtcGxlX3JlYWRzX2NvbWJpbmVkX2RmLCB4X3ZhciA9ICJyZWFkcyIsIHlfdmFyID0gInN1Y2Nlc3MiLCB4X2xvZyA9IFQpICU+JSBtdXRhdGUoeF92YXIgPSAicmVhZHMiLCB5X3ZhciA9ICJzdWNjZXNzIiksCiAgZ2V0X2xtX3N0YXRzKHN1YnNhbXBsZV9jZWxsc19jb21iaW5lZF9kZiwgeF92YXIgPSAibl9jZWxscyIsIHlfdmFyID0gImFjY3VyYWN5IiwgeF9sb2cgPSBUKSAlPiUgbXV0YXRlKHhfdmFyID0gImNlbGxzIiwgeV92YXIgPSAiYWNjdXJhY3kiKSwKICBnZXRfbG1fc3RhdHMoc3Vic2FtcGxlX2NlbGxzX2NvbWJpbmVkX2RmLCB4X3ZhciA9ICJuX2NlbGxzIiwgeV92YXIgPSAic3VjY2VzcyIsIHhfbG9nID0gVCkgJT4lIG11dGF0ZSh4X3ZhciA9ICJjZWxscyIsIHlfdmFyID0gInN1Y2Nlc3MiKQopICAlPiUgCiAgIyBmaWx0ZXIoZ3JlcGwoIl5bQUJDXSIsIGxvY3VzKSkgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgZmlsdGVyKGZpZWxkID09ICJmaWVsZF8yIikgCmBgYAoKCgojIFRhYmxlCmBgYHtyfQpjb2xfdmFycyA8LSBjKCJ4X3ZhciIsICJsb2N1cyIpCnJvd192YXJzIDwtIGMoInlfdmFyIiwgImdlbm90eXBlciIpCgpmbGV4X2RmIDwtIG1vZGVsX3N0YXRzICU+JSAKICAjIGZpbHRlcihncmVwbCgiXltBQkNdIiwgbG9jdXMpKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBmaWx0ZXIoZmllbGQgPT0gImZpZWxkXzIiKSAlPiUgCiAgbXV0YXRlKENJID0gc3ByaW50ZigiKCVzKSAtICglcykiLCBlc3RfbWluLCBlc3RfbWF4KSkgJT4lIAogIG11dGF0ZShnZW5vdHlwZXIgPSByZWZvcm1hdF9obGFfZ2Vub3R5cGVyKGdlbm90eXBlcikpICU+JSAKICBzZWxlY3QoZ2Vub3R5cGVyLCBsb2N1cywgQ0ksIHhfdmFyLCB5X3ZhcikgJT4lIAogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBjb2xfdmFycywgdmFsdWVzX2Zyb20gPSAiQ0kiLCBuYW1lc19zZXAgPSAgIi0iKSAKCmRmX2tleSA8LSB0aWJibGUoY29sX2tleXMgPSBuYW1lcyhmbGV4X2RmKSkgJT4lIAogIGZpbHRlcighKGNvbF9rZXlzICVpbiUgYyhjb2xfdmFycywgcm93X3ZhcnMpKSkgJT4lIAogIHNlcGFyYXRlKGNvbF9rZXlzLCBpbnRvID0gY29sX3ZhcnMsIHNlcCA9ICItIiwgcmVtb3ZlID0gRikgJT4lCiAgbXV0YXRlX2F0KHZhcnMoY29udGFpbnMoImdlbm90eXBlciIpKSwgcmVmb3JtYXRfaGxhX2dlbm90eXBlcikgJT4lIAogIGFycmFuZ2VfYXQoY29sX3ZhcnMpICU+JSAKICBtdXRhdGVfYWxsKGFzLmNoYXJhY3RlcikgJT4lIAogIG11dGF0ZV9hdChjb2xfdmFyc1shKGNvbF92YXJzICVpbiUgImxvY3VzIildLCBzdHJfdG9fc2VudGVuY2UpCgpmbGV4X2RmICU+JSAKICBzZWxlY3Qocm93X3ZhcnMsIGV2ZXJ5dGhpbmcoKSkgJT4lIAogIG11dGF0ZV9hdChyb3dfdmFyc1shKHJvd192YXJzICVpbiUgImdlbm90eXBlciIpXSwgc3RyX3RvX3NlbnRlbmNlKSAlPiUgCiAgIyBzZWxlY3QobG9jdXMsIGRmX2tleSRjb2xfa2V5cykgJT4lIAogIGZsZXh0YWJsZSgpICU+JSAKICBjb2xmb3JtYXRfY2hhcihuYV9zdHIgPSAiLS0tIikgJT4lCiAgbWVyZ2VfdihqPTE6MikgJT4lIAogIHNldF9oZWFkZXJfZGYobWFwcGluZyA9IGRmX2tleSwga2V5ID0gImNvbF9rZXlzIikgJT4lIAogIG1lcmdlX2gocGFydCA9ICJoZWFkZXIiKSAlPiUKICB0aGVtZV92YW5pbGxhKCkgJT4lIAogICMgdmxpbmUoaj12bGluZXNfc2VxdWVuY2UsIGJvcmRlciA9IGZwX2JvcmRlcl9kZWZhdWx0KCkpICU+JQogIGZpeF9ib3JkZXJfaXNzdWVzKCkgJT4lIAogIGF1dG9maXQoKSAlPiUgCiAgZm9udHNpemUoc2l6ZSA9IDgsIHBhcnQgPSAiYWxsIikgJT4lIAogIHByaW50KHByZXZpZXcgPSAicHB0eCIpCmBgYAoKCmBgYHtyfQogIGRmIDwtIGRmICU+JSAKICAgIG11dGF0ZShmaWVsZCA9IHJlZm9ybWF0X2hsYV9maWVsZChmaWVsZCkpICU+JSAKICAgIG11dGF0ZV9hdCh2YXJzKGNvbnRhaW5zKCJnZW5vdHlwZXIiKSksIHJlZm9ybWF0X2hsYV9nZW5vdHlwZXIpICU+JSAKICAgIG11dGF0ZShjZWxsX3ZhbHVlID0gaWZlbHNlKCFpcy5uYShzZSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ByaW50ZigiJXMgJXMgJXMiLCByb3VuZChtZWFuX2FjY3VyYWN5LDIpLCJcdTAwQjEiLHJvdW5kKHNlLDIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwcmludGYoIiVzIiwgcm91bmQobWVhbl9hY2N1cmFjeSwyKSkpKSAlPiUKICAgIG11dGF0ZShjZWxsX3ZhbHVlID0gaWZlbHNlKGdyZXBsKCJOQSIsIGNlbGxfdmFsdWUpLCBOQSwgY2VsbF92YWx1ZSkpICU+JSAKICAgIHNlbGVjdCgtc2QsLXNlLCAtbWVhbl9hY2N1cmFjeSkgJT4lIAogICAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IG5lc3RpbmdfdmFycywgdmFsdWVzX2Zyb20gPSAiY2VsbF92YWx1ZSIsIG5hbWVzX3NlcCA9ICItIikgCiAgCiAgZGZfa2V5IDwtIHN1cHByZXNzV2FybmluZ3Moe3RpYmJsZShjb2xfa2V5cyA9IG5hbWVzKGRmKSkgJT4lIAogICAgICBmaWx0ZXIoIWdyZXBsKCJsb2N1cyIsIGNvbF9rZXlzKSkgJT4lIAogICAgICBzZXBhcmF0ZShjb2xfa2V5cywgaW50byA9IG5lc3RpbmdfdmFycywgc2VwID0gIi0iLCByZW1vdmUgPSBGKSAlPiUKICAgICAgbXV0YXRlX2F0KHZhcnMoY29udGFpbnMoImdlbm90eXBlciIpKSwgcmVmb3JtYXRfaGxhX2dlbm90eXBlcikgJT4lIAogICAgICBhcnJhbmdlX2F0KG5lc3RpbmdfdmFycykgJT4lIAogICAgICBtdXRhdGVfYWxsKGFzLmNoYXJhY3RlcikKICB9KQogIAogIHZsaW5lX3ZhciA8LSB0YWlsKG5lc3RpbmdfdmFycywxKQogIHZsaW5lc19zZXF1ZW5jZSA8LSBzZXEoMSxucm93KGRmX2tleSksYnkgPSBsZW5ndGgodW5pcXVlKGRmX2tleVtbdmxpbmVfdmFyXV0pKSkKICBkZiA8LSBkZiAlPiUgCiAgICBzZWxlY3QobG9jdXMsIGRmX2tleSRjb2xfa2V5cykgJT4lIAogICAgZmxleHRhYmxlKCkgJT4lIAogICAgY29sZm9ybWF0X2NoYXIobmFfc3RyID0gIi0tLSIpICU+JSAKICAgIHNldF9oZWFkZXJfZGYobWFwcGluZyA9IGRmX2tleSwga2V5ID0gImNvbF9rZXlzIikgJT4lIAogICAgbWVyZ2VfaChwYXJ0ID0gImhlYWRlciIpICU+JSAKICAgIHRoZW1lX3ZhbmlsbGEoKSAlPiUgCiAgICB2bGluZShqPXZsaW5lc19zZXF1ZW5jZSwgYm9yZGVyID0gZnBfYm9yZGVyX2RlZmF1bHQoKSkgJT4lCiAgICBmaXhfYm9yZGVyX2lzc3VlcygpCiAgcmV0dXJuKGRmKQpgYGAKCgoKCgojIFNjcmF0Y2ggd29yawoKYGBge3IsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD0zLCB3YXJuaW5nID0gRiwgbWVzc2FnZSA9IEZ9CnN1YnNhbXBsZV9jZWxsc19jb21iaW5lZF9kZiAlPiUgCiAgZmlsdGVyKGZpZWxkID09ICJmaWVsZF8yIikgJT4lIAogIG11dGF0ZShuX2FsbGVsZXMgPSBmYWN0b3Iobl9hbGxlbGVzLCBsZXZlbHMgPSAwOjIpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gbl9hbGxlbGVzLCB5ID0gbG9nMTAobl9jZWxscykpKSsKICBnZW9tX3Zpb2xpbihzY2FsZSA9ICJ3aWR0aCIpKwogIGdlb21faml0dGVyKHNpemUgPSAwLjIsIGhlaWdodCA9IDAsIHdpZHRoID0wLjA1LCBhbHBoYSA9IDAuMikrCiAgIyBnZW9tX2JveHBsb3Qod2lkdGg9MC4xKSsKICAjIGdnYmVlc3dhcm06Omdlb21fYmVlc3dhcm0oc2l6ZSA9IDAuMSwgYWxwaGEgPSAwLjEpKwogIGNvb3JkX2ZsaXAoKSsKICBmYWNldF9ncmlkKGdlbm90eXBlciB+IGxvY3VzLCBzY2FsZXMgPSAiZnJlZSIpKwogIHRoZW1lX2J3KCkKYGBgCiMgQ292ZXJhZ2Ugc3RhdHMKYGBge3IsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD0zLCB3YXJuaW5nID0gRiwgbWVzc2FnZSA9IEZ9CnN1YnNhbXBsZV9jZWxsc19jb21iaW5lZF9kZiAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gbl9jZWxscywgeSA9IGNvdmVyYWdlLCBjb2xvciA9IGdlbm90eXBlcikpICsgCiAgZ2VvbV9wb2ludCgpICsKICBmYWNldF93cmFwKGdlbm90eXBlciB+IGxvY3VzLCBzY2FsZXMgPSAiZnJlZSIsIG5yb3cgPSAzKSArIAogIHRoZW1lX2J3KCkgKwogIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkrCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKQpgYGAKCmBgYHtyLCBmaWcud2lkdGg9MTYsIGZpZy5oZWlnaHQ9Mywgd2FybmluZyA9IEYsIG1lc3NhZ2UgPSBGfQpzdWJzYW1wbGVfY2VsbHNfY29tYmluZWRfZGYgJT4lIAogIHNlbGVjdCgtZ2Vub3R5cGVyKSAlPiUgZGlzdGluY3QoKSAlPiUgCiAgbXV0YXRlKGNvdl9wZXJfY2VsbCA9IGNvdmVyYWdlL25fY2VsbHMpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBsb2cxMChuX2NlbGxzKSwgeSA9IGNvdl9wZXJfY2VsbCkpICsgCiAgZ2VvbV9wb2ludChjb2xvciA9ICJibGFjayIsIGFscGhhID0gMC4xKSArCiAgc3RhdF9zbW9vdGgobWV0aG9kID0gImxtIikrCiAgIyBzdGF0X3Ntb290aCgpKwogICAgZmFjZXRfd3JhcCggfiBsb2N1cywgc2NhbGVzID0gImZyZWUiLCBucm93ID0gMSkgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gIkRhcmsyIikKYGBgCgpgYGB7ciwgZmlnLndpZHRoPTE2LCBmaWcuaGVpZ2h0PTYsIHdhcm5pbmcgPSBGLCBtZXNzYWdlID0gRn0Kc3Vic2FtcGxlX2NlbGxzX2NvbWJpbmVkX2RmICU+JSAKICBzZWxlY3QoLWdlbm90eXBlcikgJT4lIGRpc3RpbmN0KCkgJT4lIAogIGZpbHRlcighaXMubmEobl9jZWxscykpICU+JSAKICBtdXRhdGUoY292X3Blcl9jZWxsID0gY292ZXJhZ2Uvbl9jZWxscykgJT4lIAogIG11dGF0ZShuX2NlbGxzID0gY3V0KG5fY2VsbHMsIHNlcSgwLDEwMDAwLGJ5PTI1MDApLCByaWdodCA9IEYpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gbl9jZWxscywgeSA9IGNvdl9wZXJfY2VsbCkpICsgCiAgc3RhdF9zdW1tYXJ5KGZ1biA9IGZ1bmN0aW9uKHgpIG1lYW4oeCxuYS5ybT1UKSwgZ2VvbSA9ICJiYXIiKSArCiAgIyBnZW9tX3BvaW50KGNvbG9yID0gImJsYWNrIiwgYWxwaGEgPSAwLjEpICsKICAjIHN0YXRfc21vb3RoKG1ldGhvZCA9ICJsbSIpKwogICMgc3RhdF9zbW9vdGgoKSsKICBmYWNldF93cmFwKCB+IGxvY3VzLCBzY2FsZXMgPSAiZnJlZSIsIG5yb3cgPSAxKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkrCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKQpgYGAKCmBgYHtyfQpoaXN0KGN1dCgxOjEwMCwgc2VxKDEsMTAwLDEwKSkpCmBgYAoKYGBge3J9CnN1YnNhbXBsZV9jZWxsc19jb21iaW5lZF9kZiAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBjb3VudChnZW5vdHlwZXIsIGxvY3VzLCBmaWVsZCkKYGBgCmBgYHtyfQpzdWJzYW1wbGVfcmVhZHNfY29tYmluZWRfZGYgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgY291bnQoZ2Vub3R5cGVyLCBsb2N1cywgZmllbGQpCmBgYAo=